import tkinter as tk
from tkinter import ttk, messagebox
import random
from typing import List, Dict, Any


class Student:
    def __init__(self, name: str, math: int, english: int):
        self.id = random.randint(1000, 9999)  # 简化的唯一ID
        self.name = name
        self.math = math
        self.english = english

    @property
    def average(self) -> float:
        return (self.math + self.english) / 2


class StudentManagerApp:
    def __init__(self, root: tk.Tk):
        self.root = root
        self.root.title("学生成绩管理系统")
        self.root.geometry("800x600")

        # 学生数据
        self.students: List[Student] = []

        # 创建界面
        self.create_widgets()

        # 初始化示例数据
        self.init_sample_data()

    def create_widgets(self) -> None:
        # 顶部表单区域
        form_frame = ttk.Frame(self.root, padding=10)
        form_frame.pack(fill=tk.X)

        # 姓名
        ttk.Label(form_frame, text="姓名:").grid(row=0, column=0, padx=5, pady=5)
        self.name_entry = ttk.Entry(form_frame, width=20)
        self.name_entry.grid(row=0, column=1, padx=5, pady=5)

        # 数学成绩
        ttk.Label(form_frame, text="数学:").grid(row=0, column=2, padx=5, pady=5)
        self.math_entry = ttk.Entry(form_frame, width=10)
        self.math_entry.grid(row=0, column=3, padx=5, pady=5)

        # 英语成绩
        ttk.Label(form_frame, text="英语:").grid(row=0, column=4, padx=5, pady=5)
        self.english_entry = ttk.Entry(form_frame, width=10)
        self.english_entry.grid(row=0, column=5, padx=5, pady=5)

        # 添加按钮
        add_btn = ttk.Button(form_frame, text="添加学生", command=self.add_student)
        add_btn.grid(row=0, column=6, padx=10, pady=5)

        # 排序按钮
        sort_frame = ttk.Frame(self.root, padding=10)
        sort_frame.pack(fill=tk.X)

        math_sort_btn = ttk.Button(sort_frame, text="按数学排序", command=lambda: self.sort_students("math"))
        math_sort_btn.pack(side=tk.LEFT, padx=5)

        english_sort_btn = ttk.Button(sort_frame, text="按英语排序", command=lambda: self.sort_students("english"))
        english_sort_btn.pack(side=tk.LEFT, padx=5)

        avg_sort_btn = ttk.Button(sort_frame, text="按平均分排序", command=lambda: self.sort_students("average"))
        avg_sort_btn.pack(side=tk.LEFT, padx=5)

        # 学生列表表格
        columns = ("id", "name", "math", "english", "average")
        self.tree = ttk.Treeview(self.root, columns=columns, show="headings")

        # 设置列标题
        self.tree.heading("id", text="ID")
        self.tree.heading("name", text="姓名")
        self.tree.heading("math", text="数学")
        self.tree.heading("english", text="英语")
        self.tree.heading("average", text="平均分")

        # 设置列宽
        self.tree.column("id", width=80)
        self.tree.column("name", width=150)
        self.tree.column("math", width=100)
        self.tree.column("english", width=100)
        self.tree.column("average", width=100)

        self.tree.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 右键菜单
        self.popup_menu = tk.Menu(self.root, tearoff=0)
        self.popup_menu.add_command(label="查看详情", command=self.show_details)
        self.popup_menu.add_command(label="删除学生", command=self.delete_student)

        # 绑定右键事件
        self.tree.bind("<Button-3>", self.show_popup)

        # 状态栏
        self.status_var = tk.StringVar(value="就绪")
        status_bar = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.pack(side=tk.BOTTOM, fill=tk.X)

    def init_sample_data(self) -> None:
        # 添加示例数据
        sample_students = [
            ("张三", 90, 85),
            ("李四", 78, 92),
            ("王五", 95, 88),
            ("赵六", 82, 79),
            ("孙七", 88, 94)
        ]

        for name, math, english in sample_students:
            student = Student(name, math, english)
            self.students.append(student)

        self.update_treeview()

    def update_treeview(self) -> None:
        # 清空表格
        for item in self.tree.get_children():
            self.tree.delete(item)

        # 填充表格
        for student in self.students:
            self.tree.insert("", tk.END, values=(
                student.id,
                student.name,
                student.math,
                student.english,
                f"{student.average:.2f}"
            ))

        # 更新状态栏
        self.status_var.set(f"共 {len(self.students)} 名学生")

    def add_student(self) -> None:
        # 获取输入
        name = self.name_entry.get().strip()
        try:
            math = int(self.math_entry.get())
            english = int(self.english_entry.get())
        except ValueError:
            messagebox.showerror("输入错误", "成绩必须是数字!")
            return

        # 验证输入
        if not name:
            messagebox.showerror("输入错误", "姓名不能为空!")
            return

        if not (0 <= math <= 100 and 0 <= english <= 100):
            messagebox.showerror("输入错误", "成绩必须在0-100之间!")
            return

        # 创建学生对象并添加到列表
        student = Student(name, math, english)
        self.students.append(student)

        # 更新表格
        self.update_treeview()

        # 清空输入框
        self.name_entry.delete(0, tk.END)
        self.math_entry.delete(0, tk.END)
        self.english_entry.delete(0, tk.END)

        # 显示成功消息
        self.status_var.set(f"已添加学生: {name}")

    def sort_students(self, field: str) -> None:
        # 根据指定字段排序
        if field == "math":
            self.students.sort(key=lambda s: s.math, reverse=True)
        elif field == "english":
            self.students.sort(key=lambda s: s.english, reverse=True)
        elif field == "average":
            self.students.sort(key=lambda s: s.average, reverse=True)

        # 更新表格
        self.update_treeview()

        # 更新状态栏
        self.status_var.set(f"已按{field}排序")

    def show_popup(self, event: tk.Event) -> None:
        # 右键点击时显示菜单
        item = self.tree.identify_row(event.y)
        if item:
            self.tree.selection_set(item)
            self.popup_menu.post(event.x_root, event.y_root)

    def get_selected_student(self) -> Student | None:
        # 获取选中的学生
        selected_items = self.tree.selection()
        if not selected_items:
            return None

        item = selected_items[0]
        student_id = int(self.tree.item(item, "values")[0])

        # 查找对应的学生对象
        for student in self.students:
            if student.id == student_id:
                return student

        return None

    def show_details(self) -> None:
        # 显示学生详情
        student = self.get_selected_student()
        if not student:
            messagebox.showinfo("提示", "请先选择一名学生")
            return

        # 创建详情窗口
        detail_window = tk.Toplevel(self.root)
        detail_window.title(f"{student.name} 的详情")
        detail_window.geometry("300x200")
        detail_window.resizable(False, False)

        ttk.Label(detail_window, text=f"姓名: {student.name}").pack(pady=10)
        ttk.Label(detail_window, text=f"数学成绩: {student.math}").pack(pady=5)
        ttk.Label(detail_window, text=f"英语成绩: {student.english}").pack(pady=5)
        ttk.Label(detail_window, text=f"平均分: {student.average:.2f}").pack(pady=10)

        ttk.Button(detail_window, text="关闭", command=detail_window.destroy).pack(pady=20)

    def delete_student(self) -> None:
        # 删除选中的学生
        student = self.get_selected_student()
        if not student:
            messagebox.showinfo("提示", "请先选择一名学生")
            return

        # 确认删除
        confirm = messagebox.askyesno("确认删除", f"确定要删除 {student.name} 吗?")
        if not confirm:
            return

        # 从列表中删除
        self.students = [s for s in self.students if s.id != student.id]

        # 更新表格
        self.update_treeview()

        # 显示成功消息
        self.status_var.set(f"已删除学生: {student.name}")


if __name__ == "__main__":
    root = tk.Tk()
    app = StudentManagerApp(root)
    root.mainloop()